<template>
  <div>
    <div>
      <el-upload
        :action="uploadUrl"
        :before-upload="handleBeforeUpload"
        :on-success="handleUploadSuccess"
        :on-error="handleUploadError"
        name="file"
        :show-file-list="false"
        :headers="headers"
        class="editor-img-uploader"
        v-if="type == 'url'"
      >
        <i ref="uploadRef" class="editor-img-uploader"></i>
      </el-upload>
    </div>
    <div class="editor">
      <quill-editor
        ref="quillEditorRef"
        v-model:content="content"
        contentType="html"
        @textChange="handleTextChange"
        @compositionstart="onCompositionStart"
        @compositionend="onCompositionEnd"
        :options="options"
        :style="styles"
      />
    </div>
  </div>
</template>

<script setup>
import { QuillEditor } from "@vueup/vue-quill";
import "@vueup/vue-quill/dist/vue-quill.snow.css";
import { getToken } from "@/utils/auth";

const { proxy } = getCurrentInstance();

const quillEditorRef = ref();
const uploadUrl = ref(import.meta.env.VITE_APP_BASE_API + "/common/upload"); // 上传的图片服务器地址
const headers = ref({
  Authorization: "Bearer " + getToken()
});
const emit = defineEmits(["update:modelValue", "update:wordCount"]);

// 标志位，用于判断是否正在进行组合输入
const isComposing = ref(false);

const props = defineProps({
  /* 编辑器的内容 */
  modelValue: {
    type: String
  },
  /* 高度 */
  height: {
    type: Number,
    default: null
  },
  /* 最小高度 */
  minHeight: {
    type: Number,
    default: null
  },
  /* 只读 */
  readOnly: {
    type: Boolean,
    default: false
  },
  /* 上传文件大小限制(MB) */
  fileSize: {
    type: Number,
    default: 20
  },
  /* 类型（base64格式、url格式） */
  type: {
    type: String,
    default: "url"
  },
  /* 字数统计 */
  wordCount: {
    type: Number,
    default: 0
  }
});

const options = ref({
  theme: "snow",
  bounds: document.body,
  debug: "warn",
  modules: {
    // 工具栏配置
    toolbar: [
      ["bold"],
      [{ color: [] }],
      [{ background: [] }],
      [{ list: "ordered" }],
      [{ list: "bullet" }],
      ["blockquote"],
      [{ align: [] }],
      ["clean"],
      ["link"],
      ["video"]
      // ["image"],
    ]
  },
  placeholder: "开始写下今天的故事...",
  readOnly: props.readOnly
});

const styles = computed(() => {
  let style = {};
  if (props.minHeight) {
    style.minHeight = `${props.minHeight}px`;
  }
  if (props.height) {
    style.height = `${props.height}px`;
  }
  return style;
});

const content = ref("");
// watch(
//   () => props.modelValue,
//   v => {
//     if (v !== content.value) {
//       content.value = v === undefined ? "<p></p>" : v;
//     }
//     // 手动设置 Quill 编辑器的内容    问题：这会使光标一直在最左侧
//     if (quillEditorRef.value) {
//       quillEditorRef.value.setHTML(content.value);
//     }
//   },
//   { immediate: true }
// );
const firstLoad = ref(true);
watch(
  () => props.modelValue,
  v => {
    if (firstLoad.value) {
      content.value = v === undefined ? "<p></p>" : v;
      if (quillEditorRef.value) {
        quillEditorRef.value.setHTML(content.value);
      }
      firstLoad.value = false;
    } else if (v !== content.value) {
      content.value = v;
      if (quillEditorRef.value) {
        quillEditorRef.value.setHTML(content.value);
      }
    }
  },
  { immediate: true }
);

// 如果设置了上传地址则自定义图片和视频上传事件
onMounted(() => {
  if (props.type == "url") {
    let quill = quillEditorRef.value.getQuill();
    let toolbar = quill.getModule("toolbar");
    toolbar.addHandler("image", value => {
      if (value) {
        proxy.$refs.uploadRef.click();
      } else {
        quill.format("image", false);
      }
    });
    // toolbar.addHandler("video", value => {
    //   if (value) {
    //     proxy.$refs.uploadRef.click();
    //   } else {
    //     quill.format("video", false);
    //   }
    // });
  }
});

// 上传前校检格式和大小
function handleBeforeUpload(file) {
  const supportedTypes = [
    "image/jpeg",
    "image/jpg",
    "image/png",
    "image/svg",
    "video/mp4",
    "video/avi",
    "video/x-rmvb"
  ];
  const isValidType = supportedTypes.includes(file.type);
  console.log(file.type);

  // 检验文件格式
  if (!isValidType) {
    proxy.$modal.msgError(
      `文件格式错误！仅支持 ${supportedTypes
        .map(type => type.split("/")[1])
        .join(", ")} 格式。`
    );
    return false;
  }

  // 校检文件大小
  if (props.fileSize) {
    const isLt = file.size / 1024 / 1024 < props.fileSize;
    if (!isLt) {
      proxy.$modal.msgError(`上传文件大小不能超过 ${props.fileSize} MB！`);
      return false;
    }
  }

  return true;
}

// 上传成功处理
function handleUploadSuccess(res, file) {
  // 如果上传成功
  if (res.code == 200) {
    // 获取富文本实例
    let quill = toRaw(quillEditorRef.value).getQuill();
    // 获取光标位置
    let length = quill.selection.savedRange.index;
    // 获取文件类型，通过file.raw.type，而不是file.type。打印file对象查看即可
    const fileType = file.raw ? file.raw.type : undefined;

    if (fileType.startsWith("image")) {
      // 插入图片
      quill.insertEmbed(
        length,
        "image",
        import.meta.env.VITE_APP_BASE_API + res.fileName
      );
    } else if (fileType.startsWith("video")) {
      // 插入视频
      quill.insertEmbed(
        length,
        "video",
        import.meta.env.VITE_APP_BASE_API + res.fileName
      );
    }

    // 调整光标到最后
    quill.setSelection(length + 1);
  } else {
    proxy.$modal.msgError("文件插入失败");
  }
}

// 上传失败处理
function handleUploadError() {
  proxy.$modal.msgError("文件插入失败");
}

// 处理组合输入开始事件
const onCompositionStart = () => {
  isComposing.value = true;
};

// 处理组合输入结束事件
const onCompositionEnd = () => {
  isComposing.value = false;
  // 组合输入结束后，进行字数统计
  const wordCount = calculateWordCount(content.value);
  console.log(wordCount);
  emit("update:wordCount", wordCount);
};

// 计算字数
function calculateWordCount(htmlString) {
  const tempDiv = document.createElement("div");
  tempDiv.innerHTML = htmlString;
  // 获取去除 HTML 标签后的纯文本内容
  const textContent = tempDiv.textContent;
  // 检查 textContent 是否为空或仅包含空白字符
  if (!textContent || textContent.trim().length === 0) {
    return 0;
  }
  // 返回文本内容的长度
  return textContent.trim().length;
}

// 处理内容变化
function handleTextChange() {
  emit("update:modelValue", content);
  // isComposing.value 为 true 时，表示正在输入中文，不进行字数统计，否则进行字数统计
  if (!isComposing.value) {
    const wordCount = calculateWordCount(content.value);
    console.log(wordCount);
    emit("update:wordCount", wordCount);
  }
}
</script>

<style>
.editor-img-uploader {
  display: none;
}
.editor,
.ql-toolbar {
  white-space: pre-wrap !important;
  line-height: normal !important;
}
.quill-img {
  display: none;
}
.ql-snow .ql-tooltip[data-mode="link"]::before {
  content: "请输入链接地址:";
}
.ql-snow .ql-tooltip.ql-editing a.ql-action::after {
  border-right: 0px;
  content: "保存";
  padding-right: 0px;
}
.ql-snow .ql-tooltip[data-mode="video"]::before {
  content: "请输入视频地址:";
}
.ql-snow .ql-picker.ql-size .ql-picker-label::before,
.ql-snow .ql-picker.ql-size .ql-picker-item::before {
  content: "14px";
}
.ql-snow .ql-picker.ql-size .ql-picker-label[data-value="small"]::before,
.ql-snow .ql-picker.ql-size .ql-picker-item[data-value="small"]::before {
  content: "10px";
}
.ql-snow .ql-picker.ql-size .ql-picker-label[data-value="large"]::before,
.ql-snow .ql-picker.ql-size .ql-picker-item[data-value="large"]::before {
  content: "18px";
}
.ql-snow .ql-picker.ql-size .ql-picker-label[data-value="huge"]::before,
.ql-snow .ql-picker.ql-size .ql-picker-item[data-value="huge"]::before {
  content: "32px";
}
.ql-snow .ql-picker.ql-header .ql-picker-label::before,
.ql-snow .ql-picker.ql-header .ql-picker-item::before {
  content: "文本";
}
.ql-snow .ql-picker.ql-header .ql-picker-label[data-value="1"]::before,
.ql-snow .ql-picker.ql-header .ql-picker-item[data-value="1"]::before {
  content: "标题1";
}
.ql-snow .ql-picker.ql-header .ql-picker-label[data-value="2"]::before,
.ql-snow .ql-picker.ql-header .ql-picker-item[data-value="2"]::before {
  content: "标题2";
}
.ql-snow .ql-picker.ql-header .ql-picker-label[data-value="3"]::before,
.ql-snow .ql-picker.ql-header .ql-picker-item[data-value="3"]::before {
  content: "标题3";
}
.ql-snow .ql-picker.ql-header .ql-picker-label[data-value="4"]::before,
.ql-snow .ql-picker.ql-header .ql-picker-item[data-value="4"]::before {
  content: "标题4";
}
.ql-snow .ql-picker.ql-header .ql-picker-label[data-value="5"]::before,
.ql-snow .ql-picker.ql-header .ql-picker-item[data-value="5"]::before {
  content: "标题5";
}
.ql-snow .ql-picker.ql-header .ql-picker-label[data-value="6"]::before,
.ql-snow .ql-picker.ql-header .ql-picker-item[data-value="6"]::before {
  content: "标题6";
}
.ql-snow .ql-picker.ql-font .ql-picker-label::before,
.ql-snow .ql-picker.ql-font .ql-picker-item::before {
  content: "标准字体";
}
.ql-snow .ql-picker.ql-font .ql-picker-label[data-value="serif"]::before,
.ql-snow .ql-picker.ql-font .ql-picker-item[data-value="serif"]::before {
  content: "衬线字体";
}
.ql-snow .ql-picker.ql-font .ql-picker-label[data-value="monospace"]::before,
.ql-snow .ql-picker.ql-font .ql-picker-item[data-value="monospace"]::before {
  content: "等宽字体";
}
</style>
